#include <coroutine>
#include <iostream>
#include <stdexcept>

template <typename T> struct Generator {
  struct promise_type {
    // 标记是否有下一个值
    bool has_next_value = false;
    Generator get_return_object() {
      return {std::coroutine_handle<promise_type>::from_promise(*this)};
    }
    std::suspend_always initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    // co_yield 表达式调用该函数
    std::suspend_always yield_value(T value) {
      this->value = value;
      this->has_next_value = true;
      return {};
    }
    // 协程函数无返回值时，调用该函数，仅被调用一次
    void return_void() {}
    void unhandled_exception() {}

    T value;
  };
  Generator(std::coroutine_handle<promise_type> handle) : handle(handle) {}

  ~Generator() {
    if (handle)
      handle.destroy();
  }

  T get_value() {

    handle.promise().has_next_value = false;
    return handle.promise().value;
  }

  std::coroutine_handle<promise_type> handle;

  bool has_next() {
    // 判断协程是否结束
    if (handle.done()) {
      return false;
    }
    // 判断是否有下一个值
    if (!handle.promise().has_next_value) {
      handle.resume();
    }
    // 判断协程是否结束
    if (handle.done()) {
      return false;
    } else {
      return true;
    }
  }
  T next() {
    if (has_next()) {
      handle.promise().has_next_value = false;
      return handle.promise().value;
    } else {
      throw std::runtime_error("gnenerator is end!");
    }
  }
};

Generator<int> f() {
  int i = 0;
  while (i < 10) {
    co_yield i++;
  }
}

int main() {
  Generator<int> gen = f();
  while (gen.has_next()) {
    std::cout << gen.next() << std::endl;
  }
}